import os
import json
import logging
import datetime
from typing import Dict, List, Optional, Any, Union
from pathlib import Path

# 配置日志
logger = logging.getLogger(__name__)

class ConfigMetadata:
    """配置文件元数据类"""
    def __init__(
        self, 
        file_id: str, 
        file_name: str, 
        description: str = "",
        created_at: Optional[str] = None,
        modified_at: Optional[str] = None,
        key_id: Optional[str] = None,
        encryption_method: str = "AES256",
        tags: Optional[List[str]] = None,
        storage_info: Optional[Dict[str, Any]] = None,
        sync_status: str = "local_only",
        checksum: Optional[str] = None,
        version: int = 1
    ):
        """
        初始化配置文件元数据
        
        Args:
            file_id: 文件唯一ID
            file_name: 文件名称
            description: 文件描述
            created_at: 创建时间
            modified_at: 最后修改时间
            key_id: 加密密钥ID
            encryption_method: 加密方法
            tags: 标签列表
            storage_info: 存储信息
            sync_status: 同步状态
            checksum: 文件校验和
            version: 文件版本号
        """
        self.file_id = file_id
        self.file_name = file_name
        self.description = description
        self.created_at = created_at or datetime.datetime.now().isoformat()
        self.modified_at = modified_at or self.created_at
        self.key_id = key_id
        self.encryption_method = encryption_method
        self.tags = tags or []
        self.storage_info = storage_info or {}
        self.sync_status = sync_status
        self.checksum = checksum
        self.version = version
    
    def to_dict(self) -> Dict[str, Any]:
        """转换为字典"""
        return {
            "file_id": self.file_id,
            "file_name": self.file_name,
            "description": self.description,
            "created_at": self.created_at,
            "modified_at": self.modified_at,
            "key_id": self.key_id,
            "encryption_method": self.encryption_method,
            "tags": self.tags,
            "storage_info": self.storage_info,
            "sync_status": self.sync_status,
            "checksum": self.checksum,
            "version": self.version
        }
    
    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> 'ConfigMetadata':
        """从字典创建元数据对象"""
        return cls(
            file_id=data.get("file_id"),
            file_name=data.get("file_name"),
            description=data.get("description", ""),
            created_at=data.get("created_at"),
            modified_at=data.get("modified_at"),
            key_id=data.get("key_id"),
            encryption_method=data.get("encryption_method", "AES256"),
            tags=data.get("tags", []),
            storage_info=data.get("storage_info", {}),
            sync_status=data.get("sync_status", "local_only"),
            checksum=data.get("checksum"),
            version=data.get("version", 1)
        )
    
    def update_modified_time(self):
        """更新修改时间"""
        self.modified_at = datetime.datetime.now().isoformat()
        
    def increment_version(self):
        """增加版本号"""
        self.version += 1
        self.update_modified_time()

class MetadataManager:
    """元数据管理器，管理多个配置文件的元数据"""
    
    METADATA_DIR = ".secure_config_metadata"
    METADATA_INDEX = "index.json"
    
    def __init__(self, base_dir: Optional[str] = None):
        """
        初始化元数据管理器
        
        Args:
            base_dir: 元数据存储的基础目录，默认为当前目录
        """
        self.base_dir = base_dir or os.getcwd()
        self.metadata_path = os.path.join(self.base_dir, self.METADATA_DIR)
        self.index_path = os.path.join(self.metadata_path, self.METADATA_INDEX)
        self.configs_metadata: Dict[str, ConfigMetadata] = {}
        
        self._ensure_metadata_dir()
        self._load_metadata_index()
    
    def _ensure_metadata_dir(self):
        """确保元数据目录存在"""
        if not os.path.exists(self.metadata_path):
            try:
                os.makedirs(self.metadata_path, exist_ok=True)
                logger.info(f"创建元数据目录: {self.metadata_path}")
            except Exception as e:
                logger.error(f"创建元数据目录失败: {str(e)}")
                raise
    
    def _load_metadata_index(self):
        """加载元数据索引"""
        if not os.path.exists(self.index_path):
            self._save_metadata_index()
            return
        
        try:
            with open(self.index_path, 'r', encoding='utf-8') as f:
                index_data = json.load(f)
                
            for file_id, meta_data in index_data.items():
                self.configs_metadata[file_id] = ConfigMetadata.from_dict(meta_data)
            
            logger.info(f"已加载 {len(self.configs_metadata)} 个配置文件元数据")
        except Exception as e:
            logger.error(f"加载元数据索引失败: {str(e)}")
            # 如果加载失败，创建一个空索引
            self.configs_metadata = {}
            self._save_metadata_index()
    
    def _save_metadata_index(self):
        """保存元数据索引"""
        try:
            index_data = {
                file_id: metadata.to_dict() 
                for file_id, metadata in self.configs_metadata.items()
            }
            
            with open(self.index_path, 'w', encoding='utf-8') as f:
                json.dump(index_data, f, indent=2, ensure_ascii=False)
            
            logger.info(f"已保存 {len(self.configs_metadata)} 个配置文件元数据")
        except Exception as e:
            logger.error(f"保存元数据索引失败: {str(e)}")
            raise
    
    def add_config(self, metadata: ConfigMetadata) -> bool:
        """
        添加配置文件元数据
        
        Args:
            metadata: 配置文件元数据对象
            
        Returns:
            bool: 添加是否成功
        """
        if metadata.file_id in self.configs_metadata:
            logger.warning(f"配置文件ID已存在: {metadata.file_id}")
            return False
        
        self.configs_metadata[metadata.file_id] = metadata
        self._save_metadata_index()
        return True
    
    def update_config(self, metadata: ConfigMetadata) -> bool:
        """
        更新配置文件元数据
        
        Args:
            metadata: 配置文件元数据对象
            
        Returns:
            bool: 更新是否成功
        """
        if metadata.file_id not in self.configs_metadata:
            logger.warning(f"配置文件ID不存在: {metadata.file_id}")
            return False
        
        # 更新修改时间和版本
        metadata.update_modified_time()
        metadata.increment_version()
        
        # 更新元数据
        self.configs_metadata[metadata.file_id] = metadata
        self._save_metadata_index()
        return True
    
    def get_config(self, file_id: str) -> Optional[ConfigMetadata]:
        """
        获取配置文件元数据
        
        Args:
            file_id: 文件ID
            
        Returns:
            Optional[ConfigMetadata]: 配置文件元数据对象或None
        """
        return self.configs_metadata.get(file_id)
    
    def delete_config(self, file_id: str) -> bool:
        """
        删除配置文件元数据
        
        Args:
            file_id: 文件ID
            
        Returns:
            bool: 删除是否成功
        """
        if file_id not in self.configs_metadata:
            logger.warning(f"配置文件ID不存在: {file_id}")
            return False
        
        del self.configs_metadata[file_id]
        self._save_metadata_index()
        return True
    
    def list_configs(self, tags: Optional[List[str]] = None) -> List[ConfigMetadata]:
        """
        列出所有或满足特定标签的配置文件元数据
        
        Args:
            tags: 标签列表，用于筛选配置文件
            
        Returns:
            List[ConfigMetadata]: 配置文件元数据列表
        """
        if not tags:
            return list(self.configs_metadata.values())
        
        # 筛选包含指定标签的配置文件
        return [
            metadata for metadata in self.configs_metadata.values()
            if any(tag in metadata.tags for tag in tags)
        ]
    
    def update_sync_status(self, file_id: str, status: str) -> bool:
        """
        更新配置文件同步状态
        
        Args:
            file_id: 文件ID
            status: 同步状态
            
        Returns:
            bool: 更新是否成功
        """
        metadata = self.get_config(file_id)
        if not metadata:
            logger.warning(f"配置文件ID不存在: {file_id}")
            return False
        
        metadata.sync_status = status
        metadata.update_modified_time()
        self._save_metadata_index()
        return True
    
    def update_storage_info(self, file_id: str, storage_info: Dict[str, Any]) -> bool:
        """
        更新配置文件存储信息
        
        Args:
            file_id: 文件ID
            storage_info: 存储信息
            
        Returns:
            bool: 更新是否成功
        """
        metadata = self.get_config(file_id)
        if not metadata:
            logger.warning(f"配置文件ID不存在: {file_id}")
            return False
        
        metadata.storage_info = storage_info
        metadata.update_modified_time()
        self._save_metadata_index()
        return True
    
    def get_config_path(self, file_id: str) -> Optional[str]:
        """
        获取配置文件的实际路径
        
        Args:
            file_id: 文件ID
            
        Returns:
            Optional[str]: 配置文件路径或None
        """
        metadata = self.get_config(file_id)
        if not metadata:
            return None
        
        return os.path.join(self.base_dir, metadata.file_name) 